package com.atgm.mall.gmmailmember.service.impl;

import com.alibaba.fastjson.JSON;
import com.atgm.common.exception.BizCodeEnume;
import com.atgm.common.utils.GmMallUtils;
import com.atgm.common.utils.HttpClientUtils;
import com.atgm.common.vo.login.WeiboUser;
import com.atgm.common.vo.member.MemberInfoVo;
import com.atgm.mall.gmmailmember.dao.MemberLevelDao;
import com.atgm.mall.gmmailmember.dao.MemberSocialDao;
import com.atgm.mall.gmmailmember.dao.MemberWishDao;
import com.atgm.mall.gmmailmember.entity.MemberLevelEntity;
import com.atgm.mall.gmmailmember.entity.MemberSocialEntity;
import com.atgm.common.exception.MemberException;
import com.atgm.mall.gmmailmember.entity.MemberWishEntity;
import com.atgm.mall.gmmailmember.vo.req.MemberLoginVo;
import com.atgm.mall.gmmailmember.vo.req.MemberRegistVo;
import com.atgm.mall.gmmailmember.vo.req.WeiboUserShowVo;
import com.atgm.mall.gmmailmember.vo.resp.MemberLoginRespVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atgm.common.utils.PageUtils;
import com.atgm.common.utils.Query;

import com.atgm.mall.gmmailmember.dao.MemberDao;
import com.atgm.mall.gmmailmember.entity.MemberEntity;
import com.atgm.mall.gmmailmember.service.MemberService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Slf4j
@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Resource
    private MemberLevelDao memberLevelDao;

    @Autowired
    private MemberSocialDao memberSocialDao;

    @Autowired
    private MemberWishDao memberWishDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void regist(MemberRegistVo vo) {
        log.info("用户信息 : {}", vo);
        MemberEntity memberEntity = new MemberEntity();

        //设置默认等级
        MemberLevelEntity levelEntity = memberLevelDao.getDefaultLevel();
        memberEntity.setLevelId(levelEntity.getId());

        //设置其它的默认信息
        //检查用户名和手机号是否唯一。感知异常，异常机制
        checkPhoneUnique(vo.getMobile());
        checkUserNameUnique(vo.getUsername());

        //设置用户id
        memberEntity.setId(GmMallUtils.createMemberId());

        memberEntity.setNickname(vo.getUsername());
        memberEntity.setUsername(vo.getUsername());
        //密码进行MD5加密
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encodePwd = bCryptPasswordEncoder.encode(vo.getPassword());
        log.info("密码 : {}", encodePwd);
        memberEntity.setPassword(encodePwd);
        memberEntity.setMobile(vo.getMobile());
        memberEntity.setGender(0);
        memberEntity.setCreateTime(new Date());

        this.baseMapper.insert(memberEntity);
    }

    @Override
    public void checkPhoneUnique(String phone) {

        Integer phoneCount = this.baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("mobile", phone));
        if (phoneCount > 0) {
            throw new MemberException("存在相同手机号码", BizCodeEnume.REGISTRY_LOGIN.getCode());
        }
    }

    @Override
    public void checkUserNameUnique(String userName) {
        Integer usernameCount = this.baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("username", userName));
        if (usernameCount > 0) {
            throw new MemberException("存在相同用户名", BizCodeEnume.REGISTRY_LOGIN.getCode());
        }
    }

    @Override
    public MemberLoginRespVo login(MemberLoginVo vo) {
        String loginacct = vo.getLoginacct();
        String password = vo.getPassword();

        //1、去数据库查询 SELECT * FROM ums_member WHERE username = ? OR mobile = ?
        MemberEntity memberEntity = this.baseMapper.selectOne(new QueryWrapper<MemberEntity>()
                .eq("username", loginacct).or().eq("mobile", loginacct));

        MemberLoginRespVo memberLoginRespVo = new MemberLoginRespVo();
        if (memberEntity == null) {
            //登录失败
            return null;
        } else {
            //获取到数据库里的password
            String passwordDb = memberEntity.getPassword();
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            //进行密码匹配
            boolean matches = passwordEncoder.matches(password, passwordDb);
            if (!matches) {  //登录不成功
                throw new MemberException("密码输入错误", BizCodeEnume.USER_LOGIN.getCode());
            }

            QueryWrapper<MemberWishEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("game_id");
            queryWrapper.eq("member_id", memberEntity.getId());
            List<MemberWishEntity> memberWishEntities = memberWishDao.selectList(queryWrapper);
            if (GmMallUtils.isNotEmpty(memberWishEntities)) {
                //获取用户的心愿单ids
                List<Long> selectIds = memberWishEntities.stream().map(MemberWishEntity::getGameId).collect(Collectors.toList());
                List<String> wishGameIds = selectIds.stream().map(String :: valueOf).collect(Collectors.toList());
                memberLoginRespVo.setMemberWishIds(wishGameIds);
            }
            BeanUtils.copyProperties(memberEntity, memberLoginRespVo);
            return memberLoginRespVo;
        }
    }

    // TODO 处理服务容错
    @Transactional
    @Override
    public String weiboLogin(WeiboUser weiboUser) {
        String uid = weiboUser.getUid();
        //判断当前社交用户id是否登录过系统
        MemberEntity memberEntity = null;
        MemberSocialEntity memberSocialEntity = memberSocialDao.selectById(uid);
        long memberId = 0L;
        if (GmMallUtils.isNotEmpty(memberSocialEntity)) {
            //修改令牌等信息
            memberSocialEntity.setAccessToken(weiboUser.getAccess_token());
            memberSocialEntity.setExpiresIn(weiboUser.getExpires_in());
            memberSocialEntity.setUpdateTime(new Date());
            int count = memberSocialDao.updateById(memberSocialEntity);

            //获取用户信息
            memberEntity = baseMapper.selectById(memberSocialEntity.getMemberId());
            memberId = memberEntity.getId();
        }else {  //注册用户
            //获取微博系统中用户的信息
            Map<String, String> map = new HashMap<>();
            map.put("access_token", weiboUser.getAccess_token());
            map.put("uid", weiboUser.getUid());
            log.info("weiboUser : {}", weiboUser);
            try {
                HttpResponse response = HttpClientUtils.doGet("https://api.weibo.com", "/2/users/show.json", "get", null, map);
                if (response.getStatusLine().getStatusCode() == 200) {
                    byte[] bytes = EntityUtils.toByteArray(response.getEntity());
                    String str = new String(bytes);
                    WeiboUserShowVo weiboUserShowVo = JSON.parseObject(str, WeiboUserShowVo.class);
                    //生成用户id
                    memberId = GmMallUtils.createMemberId();
                    //系统用户id与社交用户id绑定
                    memberSocialEntity = new MemberSocialEntity();
                    memberSocialEntity.setId(Long.parseLong(weiboUser.getUid()));
                    memberSocialEntity.setMemberId(memberId);
                    memberSocialEntity.setAccessToken(weiboUser.getAccess_token());
                    memberSocialEntity.setExpiresIn(weiboUser.getExpires_in());
                    Date date = new Date();
                    memberSocialEntity.setCreateTime(date);
                    memberSocialEntity.setUpdateTime(date);
                    int count = memberSocialDao.insert(memberSocialEntity);
                    if (count != 1) {
                        throw new MemberException(BizCodeEnume.USER_LOGIN.getMsg(), BizCodeEnume.USER_LOGIN.getCode());
                    }
                    //保存用户信息
                    memberEntity = new MemberEntity();
                    memberEntity.setHeader(weiboUserShowVo.getProfile_image_url());  //头像
                    memberEntity.setGender(weiboUserShowVo.getGender().equals("m") ? 1 : 0);  //性别
                    memberEntity.setNickname(weiboUserShowVo.getScreen_name());
                    memberEntity.setUsername(weiboUserShowVo.getScreen_name());
                    memberEntity.setId(memberId);
                    memberEntity.setCreateTime(new Date());
                    count = baseMapper.insert(memberEntity);
                    if (count != 1) {
                        throw new MemberException(BizCodeEnume.REGISTRY_LOGIN.getMsg(), BizCodeEnume.REGISTRY_LOGIN.getCode());
                    }
                }else {
                    throw new MemberException(BizCodeEnume.REGISTRY_LOGIN.getMsg(), BizCodeEnume.REGISTRY_LOGIN.getCode());
                }
            }catch (Exception e) {
                e.printStackTrace();
                throw new MemberException(BizCodeEnume.REGISTRY_LOGIN.getMsg(), BizCodeEnume.REGISTRY_LOGIN.getCode());
            }
        }
        //TODO 登录成功，将登录信息存入redis

        return String.valueOf(memberId);
    }

    @Override
    public List<MemberInfoVo> queryMemberInfo(List<Long> memberIds) {
        QueryWrapper<MemberEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", memberIds);
        List<MemberEntity> memberEntityList = baseMapper.selectList(queryWrapper);

        List<MemberInfoVo> list = new LinkedList<>();

        memberEntityList.forEach(memberEntity -> {
            MemberInfoVo memberInfoVo = new MemberInfoVo();
            BeanUtils.copyProperties(memberEntity, memberInfoVo);
            list.add(memberInfoVo);
        });
        return list;
    }
}